//
//  WebRTCHelper.m
//  WebRTC_new
//
//  Created by
//  Copyright © 2020年
//

#import "WebRTCHelper.h"

#define kAPPID  @"1234567890abcdefg"
#define kDeviceUUID [[[UIDevice currentDevice] identifierForVendor] UUIDString]

//google提供的
static NSString *const RTCSTUNServerURL = @"stun:stun.l.google.com:19302";
//static NSString *const RTCSTUNServerURL2 = @"stun:23.21.150.121";
static NSString *const RTCSTUNServerURL2 =@"stun:global.stun.twilio.com:3478?transport=udp";


@interface WebRTCHelper()<RTCPeerConnectionDelegate,RTCVideoCapturerDelegate,SRWebSocketDelegate>
{
    SRWebSocket *_socket;
    NSString *_server;
    
    RTCPeerConnectionFactory *_factory;
    RTCMediaStream *_localStream;
    
    NSString *_myId;
    NSMutableDictionary *_connectionDic; // 存放 所有用户 对应的链接集合
    NSMutableArray *_connectionIdArray; // 存放 房间人数的 id
    
    NSMutableArray *ICEServers;
  
    //是否显示我的视频流（默认为yes，显示；no为不显示）
    BOOL _usingCamera;
    
    RTCCameraVideoCapturer * _capture;
}

@end

@implementation WebRTCHelper

static WebRTCHelper * instance = nil;

+(instancetype)shareInstance{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[[self class] alloc] init];
        [instance initData];
    });
    return instance;
}

-(void)initData{
    _connectionDic = [NSMutableDictionary dictionary];
    _connectionIdArray = [NSMutableArray array];
    _usingCamera = YES;
}


#pragma mark -提供给外部的方法

/**
 * 与服务器进行连接
 */
- (void)connectServer:(NSString *)server port:(NSString *)port{
    _server = server;
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"ws://%@:%@",server,port]] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20];

    _socket = [[SRWebSocket alloc] initWithURLRequest:request];
    _socket.delegate = self;
    [_socket open];

    
}


/**
 *  退出房间
 */
- (void)exitRoom
{
    _localStream = nil;
    [_capture stopCapture];
    _capture = nil;
    NSArray *arr =_connectionIdArray.copy;
    [arr enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL * _Nonnull stop) {
      [self closePeerConnection:obj];

    }];
    [_socket close];
}

/**
 * 切换摄像头
 */
- (void)swichCamera:(BOOL)_usingFrontCamera{

    [self switchFrontBackCamera:_usingFrontCamera];
}

/**
 * 是否显示本地摄像头
 */
- (void)showLocaolCamera:(BOOL)_usingCamera{
    _usingCamera = _usingCamera;
    //如果为空，则创建点对点工厂
    if (!_factory)
    {
        //设置SSL传输
        [RTCPeerConnectionFactory initialize];
        [self create_factory];
    }
    //如果本地视频流为空
    if (!_localStream)
    {
        //创建本地流
        [self createLocalStream];
    }
//    [_capture stopCapture];
    //创建连接
    [self createPeerConnections];
    
    //添加
    [self addStreams];
    [self createOffers];
}

#pragma mark -内部方法
/**
 *  关闭peerConnection
 *
 *  @param connectionId <#connectionId description#>
 */
- (void)closePeerConnection:(NSString *)connectionId
{
    RTCPeerConnection *peerConnection = [_connectionDic objectForKey:connectionId];
    if (peerConnection)
    {
        [peerConnection close];
    }
    [_connectionIdArray removeObject:connectionId];
    [_connectionDic removeObjectForKey:connectionId];
    dispatch_async(dispatch_get_main_queue(), ^{
        if ([self->_delegate respondsToSelector:@selector(webRTCHelper:closeWithUserId:)])
        {
            [self->_delegate webRTCHelper:self closeWithUserId:connectionId];
        }
    });
}


/**
 *  创建点对点连接
 *
 *  @param connectionId connectionId description
 *
 *  @return <#return value description#>
 */
- (RTCPeerConnection *)createPeerConnection:(NSString *)connectionId
{
    //如果点对点工厂为空
    if (!_factory)
    {
        [self create_factory];
    }
    
    //得到ICEServer
    if (!ICEServers) {
        ICEServers = [NSMutableArray array];
        [ICEServers addObject:[self defaultSTUNServer]];
    }
    
    //用工厂来创建连接
    RTCConfiguration *configuration = [[RTCConfiguration alloc] init];
    configuration.iceServers = ICEServers;
    RTCPeerConnection *connection = [_factory peerConnectionWithConfiguration:configuration constraints:[self creatPeerConnectionConstraint] delegate:self];
    return connection;
}

- (RTCMediaConstraints *)creatPeerConnectionConstraint
{
    RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:@{kRTCMediaConstraintsOfferToReceiveAudio:kRTCMediaConstraintsValueTrue,kRTCMediaConstraintsOfferToReceiveVideo:kRTCMediaConstraintsValueTrue} optionalConstraints:@{@"DtlsSrtpKeyAgreement":@"true"}];
    
    return constraints;
}

//初始化STUN Server （ICE Server）
- (RTCIceServer *)defaultSTUNServer{
    return [[RTCIceServer alloc] initWithURLStrings:@[RTCSTUNServerURL,RTCSTUNServerURL2]];
}


/**
 *  为所有连接添加流
 */
- (void)addStreams
{
    //给每一个点对点连接，都加上本地流
    NSDictionary *dic = [_connectionDic copy];
    [dic enumerateKeysAndObjectsUsingBlock:^(NSString *key, RTCPeerConnection *obj, BOOL * _Nonnull stop) {
        if (!self->_localStream)
        {
            [self createLocalStream];
        }
        [obj addStream:self->_localStream];
    }];
}
/**
 *  创建所有连接
 */
- (void)createPeerConnections
{
    //从我们的连接数组里快速遍历
    NSArray *arr = _connectionIdArray.copy;
    [arr enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        //根据连接ID去初始化 RTCPeerConnection 连接对象
        RTCPeerConnection *connection = [self createPeerConnection:obj];
        
        //设置这个ID对应的 RTCPeerConnection对象
        [self->_connectionDic setObject:connection forKey:obj];
       
    }];
}


/**
 * 创建本地视频流
 */
-(void)createLocalStream{
    _localStream = [_factory mediaStreamWithStreamId:@"ARDAMS"];
    //音频
    RTCAudioTrack * audioTrack = [_factory audioTrackWithTrackId:@"ARDAMSa0"];
    [_localStream addAudioTrack:audioTrack];
    NSArray<AVCaptureDevice *> *captureDevices = [RTCCameraVideoCapturer captureDevices];
    AVCaptureDevicePosition position =  AVCaptureDevicePositionFront;
    AVCaptureDevice * device = captureDevices[0];
    for (AVCaptureDevice *obj in captureDevices) {
        if (obj.position == position) {
            device = obj;
            break;
        }
    }
    
    //检测摄像头权限
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
    {
        NSLog(@"相机访问受限");
        if ([_delegate respondsToSelector:@selector(webRTCHelper:setLocalStream:userId:)])
        {
            
            [_delegate webRTCHelper:self setLocalStream:nil userId:_myId];
        }
    }
    else
    {
        if (device)
        {
            
            RTCVideoSource *videoSource = [_factory videoSource];
              [videoSource adaptOutputFormatToWidth:640 height:480 fps:20];
         _capture = [[RTCCameraVideoCapturer alloc] initWithDelegate:videoSource];
//            AVCaptureDeviceFormat * format = [[RTCCameraVideoCapturer supportedFormatsForDevice:device] lastObject];
             AVCaptureDeviceFormat* format = device.activeFormat;

            RTCVideoTrack *videoTrack = [_factory videoTrackWithSource:videoSource trackId:@"ARDAMSv0"];
            __weak RTCCameraVideoCapturer *weakCapture = _capture;
            [_localStream addVideoTrack:videoTrack];
            if ([self->_delegate respondsToSelector:@selector(webRTCHelper:capturerSession:)])
            {
                [self->_delegate webRTCHelper:self capturerSession:weakCapture.captureSession];
            }
      
              [weakCapture stopCapture];
            [weakCapture startCaptureWithDevice:device format:format fps:20 completionHandler:^(NSError * error) {
                NSLog(@"11111111");
            }];
        }
        else
        {
            NSLog(@"该设备不能打开摄像头");
            if ([_delegate respondsToSelector:@selector(webRTCHelper:setLocalStream:userId:)])
            {
                [_delegate webRTCHelper:self setLocalStream:nil userId:_myId];
            }
        }
    }
}
// 切换摄像头
-(void)switchFrontBackCamera:(BOOL)usingFrontCamera
{
    if (_localStream == nil)
        return;
    
    NSArray<AVCaptureDevice *> *captureDevices = [RTCCameraVideoCapturer captureDevices];
    AVCaptureDevicePosition position = usingFrontCamera ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack;
    AVCaptureDevice * device = nil;
    for (AVCaptureDevice *obj in captureDevices) {
        if (obj.position == position) {
            device = obj;
            break;
        }
    }
    
//    AVCaptureDeviceFormat * format = [[RTCCameraVideoCapturer supportedFormatsForDevice:device] lastObject];
     AVCaptureDeviceFormat* format = device.activeFormat;
    [_capture stopCapture];
    [_capture startCaptureWithDevice:device format:format fps:15 completionHandler:^(NSError * _Nonnull error)
     {
         
     }];
}
/**
 *  视频的相关约束
 */
- (RTCMediaConstraints *)localVideoConstraints
{
    NSDictionary *mandatory = @{kRTCMediaConstraintsMaxWidth:@640,kRTCMediaConstraintsMinWidth:@640,kRTCMediaConstraintsMaxHeight:@480,kRTCMediaConstraintsMinHeight:@480,kRTCMediaConstraintsMinFrameRate:@15};
    
    RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatory optionalConstraints:@{@"DtlsSrtpKeyAgreement":@"true"}];
    return constraints;
}

/**
 * 创建offer
 */
-(void)createOffer:(RTCPeerConnection *)peerConnection{
    if (peerConnection == nil) {
        peerConnection = [self createPeerConnection:nil];
    }
    
    [peerConnection offerForConstraints:[self offerOranswerConstraint] completionHandler:^(RTCSessionDescription * _Nullable sdp, NSError * _Nullable error) {
        if (error == nil) {
//             RTCSessionDescription *newSdp = [self descriptionForDescription:sdp preferredVideoCodec:@"H264"];
            __weak RTCPeerConnection * weakPeerConnction = peerConnection;
            [peerConnection setLocalDescription:sdp completionHandler:^(NSError * _Nullable error) {
                if (error == nil) {
                    [self setSessionDescriptionWithPeerConnection:weakPeerConnction];
                }
            }];
        }
    }];

}
/**
 *  为所有连接创建offer
 */
- (void)createOffers
{
    //给每一个点对点连接，都去创建offer
    NSDictionary *dic = [_connectionDic copy];
    [dic enumerateKeysAndObjectsUsingBlock:^(NSString *key, RTCPeerConnection *obj, BOOL * _Nonnull stop) {
        [self createOffer:obj];
    }];
}

/**
 *  设置offer/answer的约束d
 */
- (RTCMediaConstraints *)offerOranswerConstraint
{
    NSMutableDictionary * dic = [@{kRTCMediaConstraintsOfferToReceiveAudio:kRTCMediaConstraintsValueTrue,kRTCMediaConstraintsOfferToReceiveVideo:kRTCMediaConstraintsValueTrue} mutableCopy];
    [dic setObject:(_usingCamera ? kRTCMediaConstraintsValueTrue : kRTCMediaConstraintsValueFalse) forKey:kRTCMediaConstraintsOfferToReceiveVideo];
    RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:dic optionalConstraints:@{@"DtlsSrtpKeyAgreement":@"true"}];
    return constraints;
}

// Called when setting a local or remote description.
//当一个远程或者本地的SDP被设置就会调用
- (void)setSessionDescriptionWithPeerConnection:(RTCPeerConnection *)peerConnection
{
    NSLog(@"%s",__func__);
    NSString *currentId = [self getKeyFromConnectionDic:peerConnection];
   
    if (currentId == nil)
    {
        NSLog(@"找不到用户");
        return;
    }
    
    
    //判断，当前连接状态为，收到了远程点发来的offer，这个是进入房间的时候，尚且没人，来人就调到这里
    if (peerConnection.signalingState == RTCSignalingStateHaveRemoteOffer)
    {
        //创建一个answer,会把自己的SDP信息返回出去
        [peerConnection answerForConstraints:[self offerOranswerConstraint] completionHandler:^(RTCSessionDescription * _Nullable sdp, NSError * _Nullable error) {
            __weak RTCPeerConnection *obj = peerConnection;
            [peerConnection setLocalDescription:sdp completionHandler:^(NSError * _Nullable error) {
                [self setSessionDescriptionWithPeerConnection:obj];
            }];
        }];
    }
    //判断连接状态为本地发送offer
    else if (peerConnection.signalingState == RTCSignalingStateHaveLocalOffer)
    {
        if (peerConnection.localDescription.type == RTCSdpTypeAnswer)
        {
            NSDictionary *dic = @{@"event": @"answer", @"data": @{@"sdp": peerConnection.localDescription.sdp}, @"sender": _myId, @"receiver":currentId};
            NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];
            NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            [_socket send:jsonString];
            
        }
        //发送者,发送自己的offer
        else if(peerConnection.localDescription.type == RTCSdpTypeOffer)
        {
            NSDictionary *dic = @{@"event": @"offer", @"data": @{@"sdp": peerConnection.localDescription.sdp}, @"sender": _myId, @"receiver":currentId};
            NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];
             NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            [_socket send:jsonString];
        }
    }
    else if (peerConnection.signalingState == RTCSignalingStateStable)
    {
        if (peerConnection.localDescription.type == RTCSdpTypeAnswer)
        {
            NSDictionary *dic = @{@"event": @"answer", @"data": @{@"sdp": peerConnection.localDescription.sdp}, @"sender": _myId, @"receiver":currentId};
            NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];
             NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            [_socket send:jsonString];
        }
    }
    
}


#pragma mark RTCPeerConnectionDelegate
/**获取远程视频流*/
- (void)peerConnection:( RTCPeerConnection *)peerConnection didAddStream:( RTCMediaStream *)stream {
    NSString * userId = [self getKeyFromConnectionDic:peerConnection];
    dispatch_async(dispatch_get_main_queue(), ^{
        if ([self->_delegate respondsToSelector:@selector(webRTCHelper:addRemoteStream:userId:)]) {
            [self->_delegate webRTCHelper:self addRemoteStream:stream userId:userId];
        }
    });
}

/**RTCIceConnectionState 状态变化*/
- (void)peerConnection:(nonnull RTCPeerConnection *)peerConnection didChangeIceConnectionState:(RTCIceConnectionState)newState {
    NSLog(@"%s",__func__);
    NSLog(@"newState=====%ld",(long)newState);
    NSString * connectId = [self getKeyFromConnectionDic:peerConnection];
   
    if (newState == RTCIceConnectionStateDisconnected) {
//         [self createOffer:peerConnection];
        //断开connection的连接
//        dispatch_async(dispatch_get_main_queue(), ^{
//            if ([self->_delegate respondsToSelector:@selector(webRTCHelper:closeWithUserId:)]) {
//                [self->_delegate webRTCHelper:self closeWithUserId:connectId];
//            }
//            [self closePeerConnection:connectId];
//        });
    }
}
//[candidate.sdpMid isEqualToString:@"audio"]?@"audio":@"video"
/**获取到新的candidate*/
- (void)peerConnection:(RTCPeerConnection *)peerConnection didGenerateIceCandidate:(RTCIceCandidate *)candidate{
    NSLog(@"+++%s",__func__);
    
    NSString *currentId = [self getKeyFromConnectionDic: peerConnection];
    
    NSDictionary *dic = @{
                          @"event": @"_ice_candidate",
                          @"data":@{
                                  @"candidate":@{
                                          @"sdpMid":candidate.sdpMid ,
                                          @"sdpMLineIndex":[NSNumber numberWithInteger:candidate.sdpMLineIndex],
                                          @"candidate": candidate.sdp
                                          }
                                  
                                  } ,
                          @"sender":_myId ,
                          @"receiver":currentId
                          };
     NSLog(@"%d-------%@",candidate.sdpMLineIndex,candidate.sdpMid);
    NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];
      NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    [_socket send:jsonString];
}

/**删除某个视频流*/
- (void)peerConnection:(nonnull RTCPeerConnection *)peerConnection didRemoveStream:(nonnull RTCMediaStream *)stream {
    NSLog(@"%s",__func__);
}

- (void)peerConnectionShouldNegotiate:(RTCPeerConnection *)peerConnection{
    NSLog(@"%s,line = %d object = %@",__FUNCTION__,__LINE__,peerConnection);
}

- (void)peerConnection:(nonnull RTCPeerConnection *)peerConnection didRemoveIceCandidates:(nonnull NSArray<RTCIceCandidate *> *)candidates {
    NSLog(@"%s,line = %d object = %@",__FUNCTION__,__LINE__,candidates);
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeSignalingState:(RTCSignalingState)stateChanged{
     NSString *currentId = [self getKeyFromConnectionDic: peerConnection];
    
    NSLog(@"stateChanged = %ld=======currentId=====%@",(long)stateChanged,currentId);
}
- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeIceGatheringState:(RTCIceGatheringState)newState{
    NSLog(@"newState = %ld",newState);
}


#pragma mark -消息相关
-(void)peerConnection:(RTCPeerConnection *)peerConnection didOpenDataChannel:(RTCDataChannel *)dataChannel{
    
}

#pragma mark -视频分辨率代理
- (void)capturer:(nonnull RTCVideoCapturer *)capturer didCaptureVideoFrame:(nonnull RTCVideoFrame *)frame {
    
}
-(void)create_factory
{
    if(!_factory)
    {
        RTCInitializeSSL();
        RTCDefaultVideoEncoderFactory *encodeFac = [[RTCDefaultVideoEncoderFactory alloc]init];
        RTCDefaultVideoDecoderFactory *decodeFac = [[RTCDefaultVideoDecoderFactory  alloc]init];
        NSArray *arrCodecs  = [encodeFac supportedCodecs];
//        RTCVideoCodecInfo *info = arrCodecs[2];
//         RTCVideoCodecInfo *info1 = arrCodecs[2];
//        [encodeFac setPreferredCodec :info];
    
        _factory = [[RTCPeerConnectionFactory alloc]initWithEncoderFactory:encodeFac decoderFactory:decodeFac];
//        _factory = [[RTCPeerConnectionFactory alloc] init];
        }
   
}
#pragma mark --open
-(void)openWith:(NSDictionary*)dic{
    //得到data
    //得到所有的连接
    NSArray *connections = dic[@"remoteIds"];
    //加到连接数组中去
    [_connectionIdArray addObjectsFromArray:connections];
    
    //拿到给自己分配的ID
    _myId = dic[@"sender"];
    
    //如果为空，则创建点对点工厂
    if (!_factory)
    {
        //设置SSL传输
        [RTCPeerConnectionFactory initialize];
        [self create_factory];
        
    }
  
    //如果本地视频流为空
    if (!_localStream)
    {
        //创建本地流
        [self createLocalStream];
    }
    //创建连接
    [self createPeerConnections];
    
    //添加
    [self addStreams];
//    [self createOffers];
    
    //获取房间内所有用户的代理回调
    dispatch_async(dispatch_get_main_queue(), ^{
      
        if ([self->_friendDelegate respondsToSelector:@selector(webRTCHelper:gotFriendList:)]) {
            [self->_friendDelegate webRTCHelper:self gotFriendList:connections];
        }
    });
}

#pragma mark --_ice_candidate
-(void)_ice_candidateWith:(NSDictionary *)dic{
    NSDictionary *dataDic = dic[@"data"];
    NSString *socketId = dic[@"sender"];
    NSDictionary *candidateDic =dataDic[@"candidate"];
    NSString *sdpMid = candidateDic[@"sdpMid"];
    
    int sdpMLineIndex = [candidateDic[@"sdpMLineIndex"] intValue];
    NSString *sdp = candidateDic[@"candidate"];
    //生成远端网络地址对象
    RTCIceCandidate *candidate = [[RTCIceCandidate alloc] initWithSdp:sdp sdpMLineIndex:sdpMLineIndex sdpMid:sdpMid];
    //拿到当前对应的点对点连接
    RTCPeerConnection *peerConnection = [_connectionDic objectForKey:socketId];
    //添加到点对点连接中
    [peerConnection addIceCandidate:candidate];
}
#pragma mark ------join
-(void)joinWith:(NSDictionary *)dic{
    //拿到新人的ID
    NSString *socketId = dic[@"sender"];
    
    //再去创建一个连接
    RTCPeerConnection *peerConnection = [self createPeerConnection:socketId];
    if (!_localStream)
    {
        [self createLocalStream];
    }
    //把本地流加到连接中去
    [peerConnection addStream:_localStream];
    //连接ID新加一个
    [_connectionIdArray addObject:socketId];
    //并且设置到Dic中去
    [_connectionDic setObject:peerConnection forKey:socketId];

   [self createOffer:peerConnection];
    
    dispatch_async(dispatch_get_main_queue(), ^{
        //设置新加入用户代理
        if ([self->_friendDelegate respondsToSelector:@selector(webRTCHelper:gotNewFriend:)]) {
            [self->_friendDelegate webRTCHelper:self gotNewFriend:socketId];
        }
    });
}

#pragma mark --remove
-(void)removeWith:(NSDictionary *)dic{
    //得到socketId，关闭这个peerConnection
    NSString *socketId = dic[@"sender"];
    [self closePeerConnection:socketId];
    
    //设置关闭某个用户聊天代理回调
    dispatch_async(dispatch_get_main_queue(), ^{
//        if ([self->_delegate respondsToSelector:@selector(webRTCHelper:closeWithUserId:)])
//        {
//            [self->_delegate webRTCHelper:self closeWithUserId:socketId];
//        }
        //设置退出房间用户代理回调
        if ([self->_friendDelegate respondsToSelector:@selector(webRTCHelper:removeFriend:)]) {
            [self->_friendDelegate webRTCHelper:self removeFriend:socketId];
        }
    });
}

#pragma mark --offer
-(void)offerWith:(NSDictionary *)dic{
    NSDictionary *dataDic = dic[@"data"];
    //拿到SDP
    NSString *sdp = dataDic[@"sdp"];
    NSString *socketId =  dic[@"sender"];
    
    //拿到这个点对点的连接
    RTCPeerConnection *peerConnection = [_connectionDic objectForKey:socketId];
    //根据类型和SDP 生成SDP描述对象
    RTCSessionDescription *remoteSdp = [[RTCSessionDescription alloc] initWithType:RTCSdpTypeOffer sdp:sdp];
//    RTCSessionDescription *newSdp = [self descriptionForDescription:remoteSdp preferredVideoCodec:@"H264"];
    //设置给这个点对点连接
    __weak RTCPeerConnection *weakPeerConnection = peerConnection;
    [peerConnection setRemoteDescription:remoteSdp completionHandler:^(NSError * _Nullable error) {
        [self setSessionDescriptionWithPeerConnection:weakPeerConnection];
    }];
    
    //设置当前角色状态为被呼叫，（被发offer）
    //        _role = RoleCallee;
}
#pragma mark --answer
-(void)answerWith:(NSDictionary *)dic{
    NSDictionary *dataDic = dic[@"data"];
    if([dataDic count]==0){
        return;
    }
    NSString *sdp = dataDic[@"sdp"];
    
    NSString *socketId = dic[@"sender"];
    RTCPeerConnection *peerConnection = [_connectionDic objectForKey:socketId];
    RTCSessionDescription *remoteSdp = [[RTCSessionDescription alloc] initWithType:RTCSdpTypeAnswer sdp:sdp];
//    RTCSessionDescription *newSdp = [self descriptionForDescription:remoteSdp preferredVideoCodec:@"H264"];
    __weak RTCPeerConnection * weakPeerConnection = peerConnection;
    [peerConnection setRemoteDescription:remoteSdp completionHandler:^(NSError * _Nullable error) {
//                    [self setSessionDescriptionWithPeerConnection:weakPeerConnection];
    }];
}
#pragma mark WebSocketDelegate
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message{
    NSLog(@"收到服务器消息:%@",message);
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:[message dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:nil];
    NSString *eventName = dic[@"event"];
    NSLog(@"====================eventName===============%@",eventName);
    
    //1.发送加入房间后的反馈
    if ([eventName isEqualToString:@"open"])
    {
        [self openWith:dic];
        
    }
    //4.接收到新加入的人发了ICE候选，（即经过ICEServer而获取到的地址）
    else if ([eventName isEqualToString:@"_ice_candidate"])
    {
        [self _ice_candidateWith:dic];
    }
    //2.其他新人加入房间的信息
    else if ([eventName isEqualToString:@"join"])
    {
        [self joinWith:dic];
        
    }
    //有人离开房间的事件
    else if ([eventName isEqualToString:@"remove"])
    {
        [self removeWith:dic];
        
    }
    //这个新加入的人发了个offer
    else if ([eventName isEqualToString:@"offer"])
    {
        [self offerWith:dic];
    }
    //回应offer
    else if ([eventName isEqualToString:@"answer"])
    {
        [self answerWith:dic];
    }
}

- (void)webSocketDidOpen:(SRWebSocket *)webSocket{
    NSLog(@"socket连接成功");
 
    dispatch_async(dispatch_get_main_queue(), ^{
        if ([self->_delegate respondsToSelector:@selector(webRTCHelper:socketConnectState:)]) {
            [self->_delegate webRTCHelper:self socketConnectState:WebSocketConnectSuccess];
        }
    });
}

- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error{
    NSLog(@"socket连接失败");
    dispatch_async(dispatch_get_main_queue(), ^{
        if ([self->_delegate respondsToSelector:@selector(webRTCHelper:socketConnectState:)]) {
            [self->_delegate webRTCHelper:self socketConnectState:WebSocketConnectSuccess];
        }
    });
}

- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean{
    NSLog(@"socket关闭。code = %ld,reason = %@",code,reason);
    
}

- (NSString *)getKeyFromConnectionDic:(RTCPeerConnection *)peerConnection
{
    //find socketid by pc
    static NSString *socketId;
    [_connectionDic enumerateKeysAndObjectsUsingBlock:^(NSString *key, RTCPeerConnection *obj, BOOL * _Nonnull stop) {
        if ([obj isEqual:peerConnection])
        {
            NSLog(@"%@",key);
            socketId = key;
        }
    }];
    return socketId;
}

- (RTCSessionDescription *)descriptionForDescription:(RTCSessionDescription *)description preferredVideoCodec:(NSString *)codec
{
    NSString *sdpString = description.sdp;
    NSString *lineSeparator = @"\n";
    NSString *mLineSeparator = @" ";
    // Copied from PeerConnectionClient.java.
    // TODO(tkchin): Move this to a shared C++ file.
    NSMutableArray *lines =
    [NSMutableArray arrayWithArray:
     [sdpString componentsSeparatedByString:lineSeparator]];
    NSInteger mLineIndex = -1;
    NSString *codecRtpMap = nil;
    // a=rtpmap:<payload type> <encoding name>/<clock rate>
    // [/<encoding parameters>]
    NSString *pattern =
    [NSString stringWithFormat:@"^a=rtpmap:(\\d+) %@(/\\d+)+[\r]?$", codec];
    NSRegularExpression *regex =
    [NSRegularExpression regularExpressionWithPattern:pattern
                                              options:0
                                                error:nil];
    for (NSInteger i = 0; (i < lines.count) && (mLineIndex == -1 || !codecRtpMap);
         ++i) {
        NSString *line = lines[i];
        if ([line hasPrefix:@"m=video"]) {
            mLineIndex = i;
            continue;
        }
        NSTextCheckingResult *codecMatches =
        [regex firstMatchInString:line
                          options:0
                            range:NSMakeRange(0, line.length)];
        if (codecMatches) {
            codecRtpMap =
            [line substringWithRange:[codecMatches rangeAtIndex:1]];
            continue;
        }
    }
    if (mLineIndex == -1) {
        RTCLog(@"No m=video line, so can't prefer %@", codec);
        return description;
    }
    if (!codecRtpMap) {
        RTCLog(@"No rtpmap for %@", codec);
        return description;
    }
    NSArray *origMLineParts =
    [lines[mLineIndex] componentsSeparatedByString:mLineSeparator];
    if (origMLineParts.count > 3) {
        NSMutableArray *newMLineParts =
        [NSMutableArray arrayWithCapacity:origMLineParts.count];
        NSInteger origPartIndex = 0;
        // Format is: m=<media> <port> <proto> <fmt> ...
        [newMLineParts addObject:origMLineParts[origPartIndex++]];
        [newMLineParts addObject:origMLineParts[origPartIndex++]];
        [newMLineParts addObject:origMLineParts[origPartIndex++]];
        [newMLineParts addObject:codecRtpMap];
        for (; origPartIndex < origMLineParts.count; ++origPartIndex) {
            if (![codecRtpMap isEqualToString:origMLineParts[origPartIndex]]) {
                [newMLineParts addObject:origMLineParts[origPartIndex]];
            }
        }
        NSString *newMLine =
        [newMLineParts componentsJoinedByString:mLineSeparator];
        [lines replaceObjectAtIndex:mLineIndex
                         withObject:newMLine];
    } else {
        RTCLogWarning(@"Wrong SDP media description format: %@", lines[mLineIndex]);
    }
    NSString *mangledSdpString = [lines componentsJoinedByString:lineSeparator];
    return [[RTCSessionDescription alloc] initWithType:description.type
                                                   sdp:mangledSdpString];
}

@end
